#include "TcpServerSession.h"
#include "type.h"
#include "pthread_function.h"

TcpServerSession::TcpServerSession(string local_addr,
								   uint16_t local_port)
:m_local_addr(inet_addr(local_addr.c_str())),
 m_local_port(htons(local_port))
{
	m_local_struct_addr.sin_family = AF_INET;
	m_local_struct_addr.sin_addr.s_addr = m_local_addr;
	m_local_struct_addr.sin_port = m_local_port;

	m_listen_sock = socket(PF_INET, SOCK_STREAM, 0);
	if(-1 == m_listen_sock) {
		cout<<"Fail to create listening socket for tcp server session."<<endl;
		m_tcp_state = GILLINGHAM_TCP_CLOSED;
	}
	else {
		m_tcp_state = GILLINGHAM_TCP_SOCKET_CREATED;
	}
}

TcpServerSession::~TcpServerSession()
{
}

int TcpServerSession::srv_start()
{
	int ret_val;
	struct sockaddr_in remote_addr;
	socklen_t remote_addr_len = sizeof(struct sockaddr);

	if(GILLINGHAM_TCP_SOCKET_CREATED != m_tcp_state) {
		cout<<"The state of TCP is not in "
				"GILLINGHAM_TCP_SOCKET_CREATED "
				"when bind socket to local address"<<endl;
		return -1;
	}

	ret_val = bind(m_listen_sock,
				   (struct sockaddr*)&m_local_struct_addr,
				   sizeof(struct sockaddr));
	if(-1 == ret_val) {
		cout<<"Fail to bind local addr and local port for "
				"tcp server session."<<endl;
		return -1;
	}
	m_tcp_state = GILLINGHAM_TCP_BOUND;

	ret_val = listen(m_listen_sock, 5);
	m_tcp_state = GILLINGHAM_TCP_LISTENING;

	while(1) {
		TCP_CONN_SOCK_INFO* conn_sock_info_ptr = new TCP_CONN_SOCK_INFO;
		conn_sock_info_ptr->conn_sock = accept(m_listen_sock,
						   (struct sockaddr*)&remote_addr,
						   &remote_addr_len);
		if(-1 == conn_sock_info_ptr->conn_sock) {
			cout<<"Fail to accept a connected socket,"
					"failure reason is: "<<errno<<endl;
		}
		else {
			conn_sock_info_ptr->ptr_tcp_srv_session = this;
			pthread_t tid;
			ret_val = pthread_create(&tid, NULL,
									 create_tcp_srv_thread, conn_sock_info_ptr);
			if(0 != ret_val) {
				cout<<"Fail to create a thread for tcp server session,"
						"the failure reason is: "<<ret_val<<endl;
				continue;
			}
			ret_val = pthread_detach(tid);
			if(0 != ret_val) {
				cout<<"Fail to detach the new created thread, "
						"the failure reason is: "<<errno<<endl;
			}
		}
	} //while(1)

	return 0; //never executed
}

int TcpServerSession::srv_close()
{
	if(GILLINGHAM_TCP_BOUND == m_tcp_state ||
			GILLINGHAM_TCP_LISTENING ||
			GILLINGHAM_TCP_ESTABLISHED) {
		close(m_listen_sock);
	}

	return 0;
}
